package sku

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"mall/common/excption"
	"mall/common/global"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"
	"strings"
	"time"
)

type InsertSkuAttrLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewInsertSkuAttrLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InsertSkuAttrLogic {
	return &InsertSkuAttrLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *InsertSkuAttrLogic) InsertSpuAttr(in *pb.InsertSkuAttrDTO) (*pb.InsertSkuAttrVO, error) {
	// 1.check request
	checkRequestErr, spuId, valueMapper := l.checkRequestDTO(in)
	// 1.check request
	if checkRequestErr != nil {
		return nil, checkRequestErr
	}
	// 2.insert db
	spuSkuAttrValueIdArr, saveErr := l.saveDB(in, valueMapper, spuId)
	if saveErr != nil {
		return nil, saveErr
	}
	// 3.return obj
	return &pb.InsertSkuAttrVO{SkuId: in.SkuId, SpuSkuAttrValueId: spuSkuAttrValueIdArr}, nil
}

func (l *InsertSkuAttrLogic) checkRequestDTO(in *pb.InsertSkuAttrDTO) (error, int64, *mapper.SpuSkuAttrValueMapper) {
	skuMapper := mapper.NewSkuMapper()
	selectOneCtx, err := skuMapper.SelectOneCtx(l.ctx, l.svcCtx.DBEngin, bo.SkuBO{SkuId: in.SkuId})
	if err != nil {
		return err, -1, nil
	}
	if selectOneCtx.SkuId <= 0 {
		return excption.NewErrCode(constans.SkuIsDeletedError), -1, nil
	}
	spuSkuAttrValueArr := in.GetSpuAttrValueArr()
	var attrValueIdArr []int64
	for _, v := range spuSkuAttrValueArr {
		attrValueIdArr = append(attrValueIdArr, v.AttrValueId)
	}
	valueMapper := mapper.NewSpuSkuAttrValueMapper()
	selectListCtx, err := valueMapper.SelectListCtx(l.ctx, l.svcCtx.DBEngin,
		bo.SpuSkuAttrValueBO{SpuId: in.SkuId, AttrValueIdArr: attrValueIdArr})
	if err != nil {
		return err, -1, nil
	}
	if len(selectListCtx) > 0 {
		var attrValueDetail []string
		for _, v := range selectListCtx {
			attrValueDetail = append(attrValueDetail, v.AttrValueName)
		}
		printfErr := fmt.Sprintf(
			global.ErrorMessageMap[constans.SkuAttrValueRepeatError],
			strings.Join(attrValueDetail, ","),
		)
		return excption.NewErrCodeMsg(constans.SkuAttrValueRepeatError, printfErr), -1, nil
	}
	return nil, selectOneCtx.SpuId, valueMapper
}

func (l *InsertSkuAttrLogic) saveDB(in *pb.InsertSkuAttrDTO, valueMapper *mapper.SpuSkuAttrValueMapper,
	spuId int64) ([]int64, error) {
	var valueEntityArr []entity.SpuSkuAttrValueEntity
	now := time.Now()
	for _, v := range in.SpuAttrValueArr {
		valueEntity := entity.SpuSkuAttrValueEntity{}
		valueEntity.SkuId = in.SkuId
		valueEntity.SpuId = spuId
		valueEntity.AttrId = v.AttrValueId
		valueEntity.AttrValueName = v.AttrValueName
		valueEntity.AttrName = v.AttrName
		valueEntity.AttrValueId = v.AttrValueId
		valueEntity.CreateTime = now
		valueEntity.UpdateTime = now
		valueEntityArr = append(valueEntityArr, valueEntity)
	}
	spuAttrValueIdArr, err := valueMapper.BatchInsert(l.ctx, l.svcCtx.DBEngin, valueEntityArr)
	if err != nil {
		return nil, err
	}
	return spuAttrValueIdArr, nil
}
